import 'package:dio/dio.dart';
import '../config/app_config.dart';
import '../utils/storage_util.dart';

/// HTTP 请求服务
class HttpService {
  static final HttpService _instance = HttpService._internal();
  factory HttpService() => _instance;
  
  late Dio _dio;
  
  // 登录过期回调
  Function()? _onLoginExpired;
  
  // 设置登录过期回调
  void setLoginExpiredCallback(Function() callback) {
    _onLoginExpired = callback;
  }
  
  HttpService._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: AppConfig.baseUrl,
      connectTimeout: const Duration(milliseconds: AppConfig.connectTimeout),
      receiveTimeout: const Duration(milliseconds: AppConfig.receiveTimeout),
      headers: {
        'Content-Type': 'application/json',
      },
    ));
    
    // 请求拦截器
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // 添加 Token
        final token = StorageUtil.getToken();
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // 若依框架返回格式：{ code: 200, msg: '', data: {} }
        if (response.data is Map) {
          final code = response.data['code'];
          if (code != 200) {
            // 401: Token过期或未登录
            if (code == 401) {
              StorageUtil.logout();
              // 触发登录过期事件
              _onLoginExpired?.call();
              return handler.reject(
                DioException(
                  requestOptions: response.requestOptions,
                  error: '登录已过期',
                  type: DioExceptionType.badResponse,
                ),
              );
            }
            return handler.reject(
              DioException(
                requestOptions: response.requestOptions,
                error: response.data['msg'] ?? '请求失败',
                type: DioExceptionType.badResponse,
              ),
            );
          }
        }
        return handler.next(response);
      },
      onError: (error, handler) {
        String message = '网络错误';
        
        if (error.response != null) {
          switch (error.response?.statusCode) {
            case 401:
              StorageUtil.logout();
              _onLoginExpired?.call();
              message = '登录已过期';
              break;
            case 403:
              message = '拒绝访问';
              break;
            case 404:
              message = '请求错误，未找到该资源';
              break;
            case 500:
              message = '服务器错误';
              break;
            default:
              message = error.response?.data?['msg'] ?? '请求失败';
          }
        } else if (error.type == DioExceptionType.connectionTimeout) {
          message = '请求超时';
        } else if (error.type == DioExceptionType.receiveTimeout) {
          message = '响应超时';
        } else if (error.message?.contains('Network') ?? false) {
          message = '网络连接失败';
        }
        
        return handler.reject(
          DioException(
            requestOptions: error.requestOptions,
            error: message,
            type: error.type,
          ),
        );
      },
    ));
  }
  
  /// GET 请求
  Future<Response> get(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.get(
        path,
        queryParameters: queryParameters,
        options: options,
      );
    } catch (e) {
      rethrow;
    }
  }
  
  /// POST 请求
  Future<Response> post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } catch (e) {
      rethrow;
    }
  }
  
  /// PUT 请求
  Future<Response> put(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.put(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } catch (e) {
      rethrow;
    }
  }
  
  /// DELETE 请求
  Future<Response> delete(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      return await _dio.delete(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
    } catch (e) {
      rethrow;
    }
  }
  
  /// 下载文件（用于音频流）
  Future<Response> download(
    String path, {
    dynamic savePath,
    ProgressCallback? onReceiveProgress,
    Options? options,
  }) async {
    try {
      return await _dio.download(
        path,
        savePath,
        onReceiveProgress: onReceiveProgress,
        options: options,
      );
    } catch (e) {
      rethrow;
    }
  }
}

